--[[
    @Author       : baidwwy
    @Date         : 2021-02-11 11:49:09
    @LastEditTime : 2021-05-02 11:21:00
--]]

local _ENV = setmetatable({}, {__index=_G})
package.loaded.GGE界面 = _ENV
SDL = require "SDL"
窗口  = ggeassert(SDL._win,"主窗口未创建",2)
require "GUI.控件"
require "GUI.按钮"
require "GUI.输入"
require "GUI.文本"
require "GUI.列表"
require "GUI.窗口"
require "GUI.网格"
require "GUI.进度"
require "GUI.标签"
require "GUI.滑块"
local _layer = {}
local _popup,_tip,_modal = {},{},{}
local _msg = {鼠标={},键盘={},输入={},窗口={},用户={}}

窗口:注册事件(_ENV)

function 更新(dt,x,y)
    if #_tip>0 then--提示
        for i,v in ipairs(_msg.鼠标) do
            if v.type==SDL.鼠标_移动 then--鼠标移动时清空
                _tip = {}
                break
            end
        end
    
        for _,v in ipairs(_tip) do
            v:_更新(dt,x,y)
        end
    end
    
    if #_popup>0 then--弹出
        for i,v in ipairs(_popup) do
            if v._预关闭 then--下帧再关
                v:置可见(false)
                v._预关闭 = false
                table.remove(_popup, i)
                break
            end
        end
        
        local obj = _popup[#_popup]
        for i,v in ipairs(_msg.鼠标) do
            if v.type==SDL.鼠标_弹起 then--非碰撞按下时关闭
                if not obj:检查点(v.x,v.y) then
                    obj._预关闭 = true
                    break
                end
            end
        end
        
        --控件更新会截获鼠标消息，所以放在系统后面
        for i=#_popup,1,-1 do
            local v = _popup[i]
            v:_更新(dt,x,y)
            v:_消息事件(_msg)
        end
    end

    if #_modal>0 then--模态
        for i=#_modal,1,-1 do
            local v = _modal[i]
            v:_更新(dt,x,y)
            v:_消息事件(_msg)--需要在'消息事件'调用'清空消息()'
        end

        for i,v in ipairs(_modal) do
            if not v.是否可见 then
                table.remove(_modal, i)
                break
            end
        end
    end
    
    if 鼠标 then
        鼠标:消息事件(_msg)
    end
    --从最后显示的控件开始发消息
    for i=#_layer,1,-1 do
        local v = _layer[i]
        if v.是否可见 then
            v:_消息事件(_msg)
        end
    end

    _msg = {鼠标={},键盘={},输入={},窗口={},用户={}}

    for _,v in ipairs(_layer) do
        if v.是否可见 then
            v:_更新(dt,x,y)
        end
    end

    if 鼠标 and 鼠标.更新 then
        鼠标:更新(dt,x,y)
        --鼠标:消息事件(_msg)
    end
end

function 显示(x,y)
    for _,v in ipairs(_layer) do
        if v.是否可见 then
            if v._显示 then v:_显示(x,y)end
        end
    end

    for _,v in ipairs(_modal) do
        v:_显示(x,y)
    end

    for _,v in ipairs(_popup) do
        v:_显示(x,y)
    end

    if 鼠标 and 鼠标.显示 then
        鼠标:显示(x,y)
    end

    for _,v in ipairs(_tip) do
        if v.是否可见 then
            v:_显示(x,y)
        end
    end
end

function 添加模态(obj)
    for i,v in ipairs(_modal) do
        if v==obj then
            return
        end
    end
    obj:置可见(true,true)
    table.insert(_modal, obj)
end
--弹出列表，弹出右键等等（当鼠标非碰撞点击时关闭，或者置可见false）
function 添加弹出(obj)
    if not obj._预关闭 then
        obj:置可见(true,true)
        table.insert(_popup, obj)
    end
end
--鼠标停留 (当鼠标移动关闭)
function 添加提示(obj)
    for i,v in ipairs(_tip) do
        if (v.x==obj.x and v.y==obj.y) or v.名称==obj.名称 then
            return
        end
    end

    obj:置可见(true,true)
    table.insert(_tip, obj)
end

function 创建鼠标()
    鼠标 = GUI控件.创建("鼠标",0,0,窗口.宽度,窗口.高度)
    return 鼠标
end

function 创建界面(名称)
    ggeassert(not _ENV[名称], 名称..'：已存在',2)
    _ENV[名称] = GUI控件.创建(名称,0,0,窗口.宽度,窗口.高度)
    table.insert(_layer, _ENV[名称])
    return _ENV[名称]
end

function 释放界面(名称)
    local 控件 = _ENV[名称]
    if 控件 then
        控件:释放()
        for i,v in ipairs(_layer) do
            if v == 控件 then
                table.remove(_layer, i)
                释放引用(v)
                break
            end
        end
        _ENV[名称] = nil
    end
end

function 释放引用(v)
    --释放require
    for k,v1 in pairs(package.loaded) do
        if v==v1 then
            package.loaded[k] = nil
            break
        end
    end
    --释放全局
    for k,v1 in pairs(_G) do
        if v==v1 then
            _G[k] = nil
            break
        end
    end
end

function 键盘事件(...)
    table.insert(_msg.键盘, select(select("#", ...), ...))
end

function 输入事件(...)
    table.insert(_msg.输入, select(select("#", ...), ...))
end

function 鼠标事件(...)
    table.insert(_msg.鼠标, select(select("#", ...), ...))
end

-- function 窗口事件(...)
--     table.insert(_msg.窗口, select(select("#", ...), ...))
-- end

function 用户事件(...)
    table.insert(_msg.用户, select(select("#", ...), ...))
end

--模态
function 清空消息()
    for k,v in pairs(_msg) do
        if type(v)=='table' then
            for i,v in ipairs(v) do
                v.x = -9999
                v.y = -9999
            end
        end
    end
end

return _ENV